import { Button, type ButtonProps } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import type { DialogProps } from "@radix-ui/react-dialog";
import { useState } from "react";
import { toast } from "sonner";

type DataDialogButtonProps = Omit<ButtonProps, "onClick"> & {
  onClick: () => void | Promise<void>;
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export interface DataDialogProps<T = any>
  extends Pick<DialogProps, "open" | "onOpenChange" | "modal"> {
  title: React.ReactNode;
  description?: React.ReactNode;
  Component?: React.FunctionComponent<T>;
  componentProps?: T;
  className?: string;
  trigger?: React.ReactNode;
  actions?: DataDialogButtonProps[];
  children?: React.ReactNode;
}

const ButtonWithLoading: React.FC<DataDialogButtonProps> = (props) => {
  const [loading, setLoading] = useState(false);
  return (
    <Button
      {...props}
      disabled={loading || props.disabled}
      onClick={async () => {
        try {
          setLoading(true);
          await props.onClick();
        } catch (e) {
          toast.error((e as Error).message);
        } finally {
          setLoading(false);
        }
      }}
    />
  );
};

function DataDialog<T extends object = Record<string, unknown>>({
  title,
  description,
  Component,
  componentProps,
  className,
  trigger,
  actions,
  children,
  ...dialogProps
}: DataDialogProps<T>) {
  let content = children;
  if (Component) {
    content = <Component {...(componentProps as T)} />;
  }

  return (
    <Dialog {...dialogProps}>
      {trigger && <DialogTrigger>{trigger}</DialogTrigger>}
      <DialogContent className={className}>
        <DialogHeader>
          <DialogTitle>{title}</DialogTitle>
          {description && <DialogDescription>{description}</DialogDescription>}
        </DialogHeader>
        {content}
        {actions && actions.length > 0 && (
          <DialogFooter>
            {actions.map((action, index) => (
              <ButtonWithLoading key={index} {...action} />
            ))}
          </DialogFooter>
        )}
      </DialogContent>
    </Dialog>
  );
}

export default DataDialog;
